package com.cyou.weplay.service.impl;

import com.cyou.weplay.cache.layer.NicknameManageLayer;
import com.cyou.weplay.cache.layer.UserHashLayer;
import com.cyou.weplay.cache.layer.UsertokenLayer;
import com.cyou.weplay.cache.model.UserHash;
import com.cyou.weplay.redis.JedisConnection;
import com.cyou.weplay.redis.JedisConnectionUtils;
import com.cyou.weplay.service.BaseService;
import com.cyou.weplay.service.api.SystemService;
import com.cyou.weplay.service.api.UserService;
import com.cyou.weplay.service.bean.UserBean;
import com.cyou.weplay.service.exception.ServiceException;
import com.cyou.weplay.utils.RandomStringUtils;
import com.cyou.weplay.utils.SecurityUtils;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.JedisCommands;
import redis.clients.jedis.ShardedJedis;

/**
 * UserServiceImpl
 *
 * @author zhaomingyu
 */
public class UserServiceImpl extends BaseService implements UserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    private SystemService systemService;

    public void setSystemService(SystemService systemService) {
        this.systemService = systemService;
    }

    @Override
    public UserBean getUserBean(long uid) throws Exception {
        UserHash userhash = new UserHash(uid, new UserHashLayer(tableShardManager));

        JedisConnection jedisConn = JedisConnectionUtils.getJedisConnection(jedisPool);
        ShardedJedis jedis = jedisConn.getJedis();

        userhash.getAllFields(jedis);

        JedisConnectionUtils.releaseJedisConnection(jedisConn, jedisPool);
        UserBean user = userhash.getEntityBean();
        return user;
    }

    private long generateUserId() throws ServiceException {
        return systemService.incrAndGet("user_id");
    }

    @Override
    public UserBean createUserBean(long uid, String nickname, int status, String udid, String imei, String imsi, String sysid) throws Exception {
        if (uid == 0) {
            uid = generateUserId();
        }
        if (nickname == null) {
            String nicknmPrefix = systemService.getGlobalVar("nickname_prefix");
            nickname = nicknmPrefix + uid;
        }
        NicknameManageLayer nmlayer = new NicknameManageLayer(tableShardManager);
        try {
            nmlayer.createNickname(uid, nickname);
        } catch (SQLException e) {
            if (logger.isDebugEnabled()) {
                logger.debug("nickname[" + nickname + "] failed. retry others");
            }
            int retry = 3;
            boolean nicknameCreated = false;
            while (retry > 0) {
                retry--;
                String retry_nickname = nickname + "_" + RandomStringUtils.randomNumeric(3);
                try {
                    nmlayer.createNickname(uid, retry_nickname);
                    nicknameCreated = true;
                    break;
                } catch (SQLException ex) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("nickname[" + retry_nickname + "] failed retry next");
                    }
                }
            }
            if(!nicknameCreated) {
                throw new ServiceException("105");
            }
        }

        UserBean user = new UserBean();
        user.setUid(uid);
        user.setNickname(nickname);
        user.setStatus(status);
        user.setUdid(udid);
        user.setImei(imei);
        user.setImsi(imsi);
        user.setSysid(sysid);
        UserHash userhash = new UserHash(user);
        UserHashLayer hashlayer = new UserHashLayer(tableShardManager);
        hashlayer.saveData(userhash);

        JedisConnection jedisConn = JedisConnectionUtils.getJedisConnection(jedisPool);
        userhash.putAllFields(jedisConn.getJedisCommands());
        JedisConnectionUtils.releaseJedisConnection(jedisConn, jedisPool);

        UsertokenLayer tokenLayer = new UsertokenLayer(tableShardManager);
        tokenLayer.createUsertoken(uid, udid, SecurityUtils.calculateUToken(uid, udid));
        return user;
    }

    @Override
    public List<UserBean> getUserBeans(Collection<Long> uids) throws Exception {
        JedisConnection jedisConn = JedisConnectionUtils.getJedisConnection(jedisPool);
        ShardedJedis jedis = jedisConn.getJedis();
        UserHashLayer hashLayer = new UserHashLayer(tableShardManager);
        List<UserBean> users = new ArrayList<UserBean>();
        for (Long uid : uids) {
            UserHash userHash = new UserHash(uid);
            userHash.setHashDataLayer(hashLayer);
            userHash.getAllFields(jedis);
            UserBean user = userHash.getEntityBean();
            if (user != null) {
                users.add(user);
            }
        }
        JedisConnectionUtils.releaseJedisConnection(jedisConn, jedisPool);
        return users;
    }

    @Override
    public Map<Long, String[]> getFieldsOfUsers(Collection<Long> uids, String... fields) throws Exception {
        JedisConnection jedisConn = JedisConnectionUtils.getJedisConnection(jedisPool);
        ShardedJedis jedis = jedisConn.getJedis();

        UserHashLayer hashLayer = new UserHashLayer(tableShardManager);
        Map<Long, String[]> map = new HashMap<Long, String[]>();
        for (Long uid : uids) {
            UserHash userHash = new UserHash(uid);
            userHash.setHashDataLayer(hashLayer);
            String[] values = userHash.getFieldValues(jedis, fields);
            if (values == null || values.length == 0) {
                continue;
            }
            map.put(uid, values);
        }
        JedisConnectionUtils.releaseJedisConnection(jedisConn, jedisPool);
        return map;
    }

    @Override
    public String[] getUserBeanFields(long uid, String... fields) throws Exception {
        JedisConnection jedisConn = JedisConnectionUtils.getJedisConnection(jedisPool);
        JedisCommands jedis = jedisConn.getJedisCommands();

        UserHash userHash = new UserHash(uid, new UserHashLayer(tableShardManager));
        String[] values = userHash.getFieldValues(jedis, fields);
        JedisConnectionUtils.releaseJedisConnection(jedisConn, jedisPool);
        return values;
    }
}
